package com.yya.ratelimiter.service;

import cn.hutool.extra.servlet.ServletUtil;
import com.yya.ratelimiter.annotation.RateLimit;
import com.yya.ratelimiter.enums.LimitType;
import com.yya.ratelimiter.exception.RateLimitException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Objects;

import static com.yya.ratelimiter.utils.RedisUtils.getRateLimitKey;

/**
 * @Autor: yuanyongan
 * @Description: 计数器固定窗口限流算法：通过redis实现
 * 因为redis是单线程的，以及lua语言的原子性，所以不需要考虑并发情况
 * 实现简单
 * @Date 2023/1/12 11:11
 */
@Service
@Slf4j
public class CounterWindow implements LimitationAlgorithm {

    @Resource
    RedisTemplate<String, Object> redisTemplate;

    @Resource
    RedisScript<Long> redisScript;

    @Override
    public void acquire(RateLimit rateLimit, MethodSignature methodSignature) {
        // 构建redis中key的值
        String rateKey = getRateLimitKey(rateLimit, methodSignature);
        System.out.println("redis中的key为" + rateKey);

        try{

            Long current = redisTemplate.execute(redisScript, Collections.singletonList(rateKey), rateLimit.time(), rateLimit.count());
            if (current == null || current.intValue() > rateLimit.count()){
                log.info("当前接口达到最大限流次数");
                throw new RateLimitException(500, "当前接口达到最大限流次数");
            }
            log.info("一段时间内允许请求的次数:{}, 当前请求次数:{}, 缓存的key为:{}", rateLimit.count(), current, rateKey);
        }catch (Exception e){
            throw e;
        }
    }

    @Override
    public void logInfo() {

    }


    public void test(){
        System.out.println("CounterWindow注入成功");
    }
}
